home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-05-13 | 23.0 KB | 1,133 lines |
- External;
-
- {
- IO.p (of PCQ Pascal)
- Copyright (c) 1989 Patrick Quaid
-
- This module handles the IO of the compiler. The actual
- compilation of the io statements is handled in stanprocs.p
- }
-
- {$O-}
- {$I "Pascal.i"}
- {$I "Include:Libraries/DOS.i" }
- {$I "Include:Utils/StringLib.i"}
- {$I "Include:Utils/Break.i"}
-
-
- Procedure Out_Operation1(op : OpCodes; Size : Byte;
- EA : EAModes; Reg : Regs);
- External;
- Procedure Out_Extension(Ext : Integer);
- External;
-
- Function EndOfFile() : Boolean;
-
- {
- This just determines when the end of all input has occured.
- }
-
- begin
- EndOfFile := (InFile = nil) and (not CharBuffed);
- end;
-
- Procedure AnnounceFile;
- begin
- if StdOut_Interactive then
- Write('\r\cK', LineNo:5, ' ', InFile^.Name, '\r');
- end;
-
- Procedure WriteLineNo;
- begin
- if StdOut_Interactive then
- Write(Chr(13), LineNo:5);
- end;
-
- Procedure CountLines;
-
- { Does the bookkeeping for errors }
-
- begin
- if CurrentChar = Chr(10) then begin
- LineNo := Succ(LineNo);
- if Inform then
- if (LineNo and 15) = 0 then
- WriteLineNo;
- end;
- end;
-
- Procedure EndComment;
- forward; { It's in this module }
-
- Procedure CloseInputFile;
-
- { This closes the current input file and restores the saved stuff }
-
- var
- TempPtr : FileRecPtr;
- Result : Short;
- begin
- if Inform and StdOut_Interactive then begin
- WriteLineNo;
- Writeln;
- end;
- Close(InFile^.PCQFile);
- Result := IOResult;
- TempPtr := InFile^.Previous;
- FreeString(InFile^.Name);
- Dispose(InFile);
- InFile := TempPtr;
- if InFile <> nil then begin
- LineNo := InFile^.SaveLine;
- FNStart := InFile^.SaveStart;
- CurrentChar := InFile^.SaveChar;
- if Inform then
- AnnounceFile;
- EndComment;
- end else
- CurrentChar := Chr(0);
- end;
-
- Procedure Abort;
-
- {
- This routine cuts out cleanly. If you are debugging the
- compiler, this is a likely place to put post mortem dumps, like the
- one commented out.
- }
- var
- Result : Short;
- begin
- While InFile <> nil do
- CloseInputFile;
- Close(OutFile);
- Result := IOResult;
- Writeln('Compilation Aborted');
- Exit(20);
- end;
-
- Function OpenInputFile(name : String) : Boolean;
-
- { This routine opens a new file record, and a new file. It also
- saves the state of the File-dependant variables, like LineNo. }
-
- var
- TempPtr : FileRecPtr;
- OpenError : Integer;
- begin
- New(TempPtr);
- if not ReOpen(name, TempPtr^.PCQFile, 10240) then begin
- Dispose(TempPtr);
- OpenError := IOResult;
- OpenInputFile := False;
- end;
- TempPtr^.Previous := InFile;
- if InFile <> nil then begin
- InFile^.SaveLine := LineNo;
- InFile^.SaveStart := FNStart;
- InFile^.SaveChar := CurrentChar;
- end;
- LineNo := 1;
- FNStart := 1;
- TempPtr^.Name := strdup(name);
- InFile := TempPtr;
- if EOF(InFile^.PCQFile) then
- CloseInputFile
- else
- Read(Infile^.PCQFile, CurrentChar);
- if Inform then
- AnnounceFile;
- OpenInputFile := True;
- end;
-
- Function EQFix(x : Short) : Integer;
-
- {
- This helps implement a queue. In this case it's for the
- error queue.
- }
-
- begin
- EQFix := x and EQSize;
- end;
-
- Procedure Error(ptr : string);
-
- {
- This just writes out at most the previous 128 characters or
- two lines, then writes the error message passed to it. If there
- are five errors, it aborts.
- }
-
- var
- index : integer;
- newlines : integer;
- Column : Short;
- LessLines : Short;
- begin
- index := EQEnd;
- newlines := 0;
- Column := 0;
- LessLines := 0;
-
- while (index <> EQStart) and (newlines < 2) do begin
- if Index = ErrorPtr then begin
- Column := 1;
- LessLines := NewLines;
- end else if LessLines = NewLines then
- Inc(Column);
-
- index := EQFix(index - 1);
- if ErrorQ[EQFix(index - 1)] = chr(10) then
- Inc(NewLines);
- end;
-
- if CurrentChar = Chr(10) then
- Inc(LessLines);
-
- if Inform then begin
- if StdOut_Interactive then
- write('\n\cK'); { newline, ClrEOL }
- while index <> EQEnd do begin
- if (index = ErrorPtr) and StdOut_Interactive then
- write('\c0;33;40m'); { start highlight for ANSI }
- write(ErrorQ[index]);
- index := EQFix(index + 1);
- end;
- if StdOut_Interactive then
- write('\c0;31;40m'); { end highlight }
- writeln;
- write('Line ', LineNo - LessLines, ' ');
- if currfn <> nil then
- write('(', CurrFn^.Name, ')');
- writeln(': ', ptr, '\n');
- end else
- Writeln('"', InFile^.Name, '" At ', LineNo - LessLines, ',',
- Column, ' : ', ptr);
- { Quiet mode, no surprises }
-
- Inc(errorcount);
- if errorcount > 3 then
- Abort;
- if CheckBreak() then
- Abort;
- if Inform then
- AnnounceFile;
- end;
-
- Procedure ReadChar;
-
- { This is the main link between the lexical analysis stuff and the
- IO stuff. It sets up CurrentChar and keeps the line count. }
- var
- IOError : Integer;
- begin
- if CheckBreak() then
- Abort;
- if CharBuffed then begin
- CurrentChar := BuffedChar;
- CharBuffed := False;
- return;
- end;
- if EOF(InFile^.PCQFile) then
- CloseInputFile
- else begin
- Read(InFile^.PCQFile, CurrentChar);
- IOError := IOResult;
- CountLines;
- end;
- EQEnd := EQFix(Succ(EQEnd));
- ErrorQ[EQEnd] := CurrentChar;
- if EQStart = EQEnd then
- EQStart := EQFix(Succ(EQStart));
- end;
-
- Function NextChar() : Char;
- var
- c : Char;
- begin
- if not CharBuffed then begin
- c := CurrentChar;
- ReadChar;
- BuffedChar := CurrentChar;
- CurrentChar := c;
- CharBuffed := True;
- end;
- NextChar := BuffedChar;
- end;
-
- Procedure EndComment;
-
- {
- This just eats characters up to the end of a comment. If
- you want nested comments, this is probably the place to do it.
- }
-
- begin
- while (Currentchar <> '}') and (not EndOfFile()) do
- ReadChar;
- if not EndOfFile() then
- ReadChar;
- end;
-
- Function GetLabel() : integer;
-
- {
- As in all compilers, this just returns a unique serial
- number.
- }
-
- begin
- Inc(NxtLab);
- getlabel := nxtlab;
- end;
-
- Procedure PrintLabel(lab : integer);
-
- {
- This routine prints a label based on a number from the
- above procedure. The prefix for the label can be anything the
- assembler accepts - in this case I wanted it similar to the prefix
- of the run time library routines. I didn't realize how ugly it
- would look.
- }
-
- begin
- write(OutFile, '_p%', lab);
- end;
-
- Function JustFileName(S : String) : String;
-
- { returns a string that is the file name part of a path. It does
- NOT allocate space. }
-
- var
- Ptr : String;
- begin
- if S^ = Chr(0) then
- JustFileName := S;
- Ptr := S;
- while Ptr^ <> Chr(0) do
- Inc(Ptr);
- Dec(Ptr);
- while (Ptr^ <> ':') and (Ptr^ <> '/') do begin
- if Ptr = S then
- JustFileName := S;
- Dec(Ptr);
- end;
- Inc(Ptr);
- JustFileName := Ptr;
- end;
-
- Procedure AddIncludeName(S : String);
-
- { Adds the name of an include file to the list, so it won't be
- included again. }
-
- var
- Ptr : IncludeRecPtr;
- begin
- Ptr := IncludeRecPtr(AllocString(strlen(S) + 5));
- if Ptr = nil then
- Abort;
- strcpy(Adr(Ptr^.Name), S);
- Ptr^.Next := IncludeList;
- IncludeList := Ptr;
- end;
-
- Function AlreadyIncluded(S : String) : Boolean;
-
- { Determines whether a file has been included already }
-
- var
- Ptr : IncludeRecPtr;
- begin
- Ptr := IncludeList;
- while Ptr <> nil do begin
- if strieq(Adr(Ptr^.Name), S) then
- AlreadyIncluded := True;
- Ptr := Ptr^.Next;
- end;
- AlreadyIncluded := False;
- end;
-
- Procedure DoInclude;
-
- {
- The name says it all. The mechanics of the include
- directive are all handled here.
- }
-
- var
- Ptr : String;
- begin
- ReadChar;
- While (CurrentChar <= ' ') and (not EndOfFile()) do
- ReadChar;
- if CurrentChar <> '"' then begin
- Error("Missing Quote");
- EndComment;
- Return;
- end;
- ReadChar;
- Ptr := SymText;
- while CurrentChar <> '"' do begin
- Ptr^ := CurrentChar;
- Inc(Ptr);
- if EndOfFile() then
- Return;
- ReadChar;
- end;
- Ptr^ := Chr(0); { mark then end of the file name }
- ReadChar; { read the end quote }
- if not AlreadyIncluded(JustFileName(SymText)) then begin
- if OpenInputFile(SymText) then
- AddIncludeName(JustFileName(SymText))
- else begin
- Error("Could not open input file");
- EndComment;
- end;
- end else
- EndComment;
- end;
-
- Procedure DoComment;
-
- {
- This routine implements compiler directives.
- }
-
- Procedure DoASM;
- var
- Buffer : Array [0..127] of Char;
- i : Byte;
-
- Procedure WriteIt;
- begin
- Buffer[i] := '\0';
- if CurrFn = Nil then
- Writeln(OutFile, String(Adr(Buffer)))
- else begin
- Out_Operation1(op_LABEL,3,ea_String,a7);
- Out_Extension(Integer(strdup(Adr(Buffer))));
- end;
- i := 0;
- end;
-
- begin
- ReadChar;
- i := 0;
- while CurrentChar <> '}' do begin
- if (CurrentChar = Chr(10)) and (i > 0) then
- WriteIt
- else begin
- Buffer[i] := CurrentChar;
- Inc(i);
- if i > 127 then
- WriteIt;
- end;
-
- if EndOfFile() then begin
- Error("File ended in a comment");
- return;
- end;
- ReadChar;
- end;
- if i > 0 then
- WriteIt;
- ReadChar;
- end;
-
- Procedure DoOnOff(var Flag : Boolean);
- begin
- ReadChar;
- if CurrentChar = '+' then
- Flag := True
- else if CurrentChar = '-' then
- Flag := False;
- end;
-
- Procedure DoStorage;
- var
- KillChar : Boolean;
- begin
- ReadChar;
- KillChar := True;
- case CurrentChar of
- 'X' : StandardStorage := st_external;
- 'P' : StandardStorage := st_private;
- 'N' : StandardStorage := st_internal;
- else begin
- Error("Unknown storage class");
- KillChar := False;
- end;
- end;
- if KillChar then
- ReadChar;
- end;
-
- begin
- readchar;
- if currentchar = '$' then begin
- repeat
- readchar; { either $ or , }
- Case CurrentChar of
- 'I' : if (NextChar = '+') or (NextChar = '-') then
- DoOnOff(IOCheck)
- else begin
- DoInclude;
- return;
- end;
- 'A' : begin
- DoASM;
- return;
- end;
- 'R' : DoOnOff(RangeCheck);
- 'O' : DoOnOff(IOCheck);
- 'S' : DoStorage;
- 'B' : DoOnOff(ShortCircuit);
- else begin
- Error("Unknown Directive");
- EndComment;
- return;
- end;
- end;
- if (CurrentChar <> ',') or EndOfFile then begin
- EndComment;
- return;
- end;
- until false;
- end else
- EndComment;
- end;
-
- Function Alpha(c : char): boolean;
-
- {
- This function answers the eternal question "is this
- character an alphabetic character?" Note that _ is.
- }
-
- begin
- c := toupper(c);
- Alpha := ((c >= 'A') and (c <= 'Z')) or (c = '_');
- end;
-
- Function AlphaNumeric(c : char): boolean;
-
- {
- Is the character a letter or digit?
- }
-
- begin
- AlphaNumeric := Alpha(c) or isdigit(c);
- end;
-
- Procedure Header;
-
- {
- This routine references all the run time library routines.
- One thing I like about A68k is that the only routines that are
- used in the assembly code end up in the object file. Maybe all
- assemblers do it, but I don't know.
- }
-
- begin
- writeln(OutFile, "* Pascal compiler intermediate assembly program.\n\n");
- writeln(OutFile, "\tSECTION\tPCQMain\n");
- writeln(OutFile, "\tXREF\t_Input");
- writeln(OutFile, "\tXREF\t_Output");
- writeln(OutFile, "\tXREF\t_p%WriteInt");
- writeln(OutFile, "\tXREF\t_p%WriteReal");
- writeln(OutFile, "\tXREF\t_p%WriteChar");
- writeln(OutFile, "\tXREF\t_p%WriteBool");
- writeln(OutFile, "\tXREF\t_p%WriteCharray");
- writeln(OutFile, "\tXREF\t_p%WriteString");
- writeln(OutFile, "\tXREF\t_p%WriteLn");
- writeln(OutFile, "\tXREF\t_p%ReadInt");
- writeln(OutFile, "\tXREF\t_p%ReadReal");
- writeln(OutFile, "\tXREF\t_p%ReadCharray");
- writeln(OutFile, "\tXREF\t_p%ReadChar");
- writeln(OutFile, "\tXREF\t_p%ReadString");
- writeln(OutFile, "\tXREF\t_p%ReadLn");
- writeln(OutFile, "\tXREF\t_p%ReadArb");
- writeln(OutFile, '\tXREF\t_p%FilePtr');
- writeln(OutFile, '\tXREF\t_p%Get');
- writeln(OutFile, '\tXREF\t_p%Put');
- writeln(OutFile, "\tXREF\t_p%dispose");
- writeln(OutFile, "\tXREF\t_p%new");
- writeln(OutFile, "\tXREF\t_p%Open");
- writeln(OutFile, "\tXREF\t_p%OpenB");
- writeln(OutFile, "\tXREF\t_p%WriteArb");
- writeln(OutFile, "\tXREF\t_p%Close");
- writeln(OutFile, "\tXREF\t_p%exit");
- writeln(OutFile, "\tXREF\t_p%lmul");
- writeln(OutFile, "\tXREF\t_p%ldiv");
- writeln(OutFile, "\tXREF\t_p%lrem");
- writeln(OutFile, "\tXREF\t_p%MathBase");
- writeln(OutFile, '\tXREF\t_p%sin');
- writeln(OutFile, '\tXREF\t_p%cos');
- writeln(OutFile, '\tXREF\t_p%sqrt');
- Writeln(OutFile, '\tXREF\t_p%tan');
- Writeln(OutFile, '\tXREF\t_p%atn');
- Writeln(OutFile, '\tXREF\t_p%ln');
- Writeln(OutFile, '\tXREF\t_p%exp');
- Writeln(OutFile, '\tXREF\t_p%CheckIO');
- Writeln(OutFile, '\tXREF\t_p%CheckRange\n');
- if mainmode then begin
- if SmallInitialize then begin
- Writeln(OutFile, '\tXREF\t_p%minimal_init');
- Writeln(OutFile, "\tjsr\t_p%minimal_init");
- end else begin
- writeln(OutFile, "\tXREF\t_p%initialize");
- writeln(OutFile, "\tjsr\t_p%initialize");
- end;
- writeln(OutFile, "\tjsr\t_MAIN");
- writeln(OutFile, '\tmoveq\t#0,d0');
- writeln(OutFile, "\tjsr\t_p%exit");
- writeln(OutFile, "\trts");
- end
- end;
-
- Procedure Trailer;
-
- {
- This routine is the most important in the compiler
- }
-
- begin
- writeln(OutFile, "\tEND");
- end;
-
- Procedure Blanks;
-
- {
- blanks() skips spaces, tabs and eoln's. It handles
- comments if it comes across one.
- }
-
- var
- done : boolean;
- begin
- while ((CurrentChar <= ' ') or (CurrentChar = '{')) and
- (not EndOfFile()) do begin
- if CurrentChar = '{' then
- DoComment
- else
- ReadChar;
- end;
- end;
-
- Procedure DumpLitQ(k : Integer);
-
- {
- This procedure dumps the literal table at the end of the
- compilation. Individual components are referenced as offsets to
- the literal label.
- }
-
- var
- j : integer;
- quotemode : boolean;
- begin
- while k < litptr do begin
- write(OutFile, "\tdc.b\t");
- j := 0;
- quotemode := false;
- while j < 40 do begin
- if (ord(litq[k]) > 31) and (ord(litq[k]) <> 39) then begin
- if quotemode then
- write(OutFile, litq[k])
- else begin
- if j > 0 then
- write(OutFile, ',');
- write(OutFile, chr(39), litq[k]);
- quotemode := true;
- end;
- end else begin
- if quotemode then begin
- write(OutFile, chr(39));
- quotemode := false;
- end;
- if j > 0 then
- write(OutFile, ',');
- write(OutFile, ord(litq[k]));
- if j > 32 then
- j := 40
- else
- j := j + 3;
- end;
- j := j + 1;
- k := k + 1;
- if k >= litptr then
- j := 40;
- end;
- if quotemode then
- write(OutFile, chr(39));
- writeln(OutFile);
- end
- end;
-
- Procedure DumpLits;
- begin
- if LitPtr = 0 then
- return;
- writeln(OutFile, '\n\tSECTION\tLITS,DATA');
- PrintLabel(LitLab);
- DumpLitQ(0);
- end;
-
- Procedure DumpIds;
-
- {
- This routine does whatever is appropriate with the various
- identifers. If it's a global, it either references it or allocates
- space. Similar stuff for the other ids. When the modularity of
- PCQ is better defined, this routine will have to do more work.
- }
-
- var
- CB : BlockPtr;
- ID : IDPtr;
- TP : TypePtr;
- i : Integer;
- isodd : boolean;
- WroteSection : Boolean;
- begin
- WroteSection := False;
- isodd := false;
- CB := CurrentBlock;
- while CB <> nil do begin
- for i := 0 to Hash_Size do begin
- ID := CB^.Table[i];
- while ID <> nil do begin
- case ID^.Object of
- global : case ID^.Storage of
- st_internal,
- st_private : begin
- if not WroteSection then begin
- writeln(OutFile, "\n\tSECTION\tSTORAGE,BSS\n");
- WroteSection := True;
- end;
- TP := ID^.VType;
- if isodd and (TP^.Size > 1) then begin
- Writeln(OutFile, "\tCNOP\t0,2");
- isodd := False;
- end;
- if ID^.Storage <> st_private then
- Writeln(OutFile,"\tXDEF\t_", ID^.Name);
- Write(OutFile, '_', ID^.Name);
- Writeln(OutFile, "\tds.b\t", TP^.Size);
- if odd(TP^.Size) then
- isodd := not isodd;
- end;
- end;
- proc,
- func : if ID^.Storage = st_forward then
- Writeln(ID^.Name, ' was never defined.');
- end;
- ID := ID^.Next;
- end;
- end;
- CB := CB^.Previous;
- end;
- end;
-
- Procedure DumpRefs;
-
- {
- This routine makes all the external references necessary.
- }
-
- var
- CB : BlockPtr;
- ID : IDPtr;
- i : Integer;
- begin
- writeln(OutFile);
- CB := CurrentBlock;
- while CB <> nil do begin
- for i := 0 to Hash_Size do begin
- ID := CB^.Table[i];
- while ID <> nil do begin
- if ID^.Storage = st_external then
- writeln(OutFile, "\tXREF\t_", ID^.Name);
- ID := ID^.Next;
- end;
- end;
- CB := CB^.Previous;
- end
- end;
-
- Procedure SearchReserved;
-
- {
- This just does a binary chop search of the list of reserved
- words.
- }
-
- var
- top,
- middle,
- bottom : Symbols;
- compare : Short;
- begin
- Bottom := And1;
- Top := LastReserved;
- while Bottom <= Top do begin
- middle := Symbols((Byte(bottom) + Byte(top)) div 2);
- Compare := stricmp(Reserved[Middle], SymText);
- if Compare = 0 then begin
- CurrSym := Middle;
- Return;
- end else if Compare < 0 then
- Bottom := Succ(Middle)
- else
- Top := Pred(Middle);
- end;
- CurrSym := Ident1;
- end;
-
- Procedure ReadWord;
-
- {
- This reads a Pascal identifier into symtext.
- }
-
- var
- ptr : string;
- begin
- ptr := symtext;
- repeat
- Ptr^ := CurrentChar;
- Ptr := String(Integer(Ptr) + 1);
- ReadChar;
- until not AlphaNumeric(CurrentChar);
- Ptr^ := chr(0);
- SearchReserved;
- end;
-
- Function DigVal(c : Char) : Integer;
- begin
- DigVal := Ord(c) - Ord('0');
- end;
-
- Procedure ReadNumber;
-
- {
- This routine reads a literal integer. Note that _ can be used.
- }
-
- var
- Divider : Real;
- Fraction : Real;
- begin
- SymLoc := 0;
- While isdigit(CurrentChar) do begin
- SymLoc := (SymLoc * 10) + DigVal(CurrentChar);
- ReadChar;
- if CurrentChar = '_' then
- ReadChar;
- end;
- CurrSym := Numeral1;
- if (CurrentChar = '.') and isdigit(NextChar()) then begin { It's real! }
- ReadChar; { skip the . }
- RealValue := Float(SymLoc);
- Divider := 1.0;
- Fraction := 0.0;
- while isdigit(CurrentChar) do begin
- Fraction := Fraction * 10.0 + Float(DigVal(CurrentChar));
- Divider := Divider * 10.0;
- ReadChar;
- end;
- RealValue := RealValue + Fraction / Divider;
- CurrSym := RealNumeral1;
- end;
- end;
-
- Procedure ReadHex;
-
- {
- readhex() reads a hexadecimal number.
- }
-
- var
- rc : integer;
- Count : Short;
- begin
- ReadChar;
- symloc := 0;
- Count := 0;
- rc := ord(toupper(currentchar));
- while isdigit(currentchar) or
- ((rc >= ord('A')) and (rc <= ord('F'))) do begin
- Inc(Count);
- SymLoc := SymLoc shl 4;
- if isdigit(currentchar) then
- symloc := symloc + ord(currentchar) - ord('0')
- else
- symloc := symloc + rc - ord('A') + 10;
- ReadChar;
- rc := ord(toupper(currentchar));
- end;
-
- if Count = 0 then
- Error("No hexadecimal digits")
- else if Count > 8 then
- Error("Constant out of range (more than 32 bits)");
-
- currsym := numeral1;
- end;
-
-
- Procedure ReadBinary;
- {
- Reads a binary number, of the form %[0|1]*
- }
- var
- Count : Short;
- begin
- ReadChar; { Read past the % }
- SymLoc := 0;
- Count := 0;
- while (CurrentChar = '0') or (CurrentChar = '1') do begin
- Inc(Count);
- SymLoc := (SymLoc shl 1) + DigVal(CurrentChar);
- ReadChar;
- end;
-
- if Count = 0 then
- Error("No binary digits")
- else if Count > 32 then
- Error("Constant out of range (more than 32 bits)");
-
- CurrSym := Numeral1;
- end;
-
- {
- Procedure ReadString;
- var
- Delim : Char;
- begin
- InStringLength := 0;
- Delim := CurrentChar;
- ReadChar;
- repeat
- if CurrentChar = Delim then begin
- ReadChar;
- if (CurrentChar = Delim) and (Delim = '\'') then begin
- Insert('\'');
- ReadChar;
- end else
- Quit := True;
- end else if CurrentChar = '#' then begin
- ReadChar;
- case CurrentChar of
- '0'..'9' : ReadNumber;
- '$' : ReadHex;
- '%' : ReadBinary;
- else begin
- Error("Expecting an integer");
- SymLoc := 0;
- CurrSym := Numeral1;
- end;
- end;
- if CurrSym <> Numeral1 then
- Error("Expecting an integer");
- if SymLoc > 255 then
- Error("Constant out of range");
- Insert(Chr(SymLoc));
- end else if CurrentChar = Chr(10) then begin
- Error("String exceeds line");
- Quit := True;
- end else if CurrentChar = '\\' then begin
- ReadChar;
- case CurrentChar of
- 'n' : Insert(Chr(10));
- 't' : Insert(Chr(9));
- '0' : Insert(Chr(0));
- 'b' : Insert(Chr(8));
- 'e' : Insert(Chr(27));
- 'c' : Insert(Chr($9B));
- 'a' : Insert(Chr(7));
- 'f' : Insert(Chr(12));
- 'r' : Insert(Chr(13));
- 'v' : Insert(Chr(11));
- else
- Insert(CurrentChar);
- end;
- ReadChar;
- end else begin
- Insert(CurrentChar);
- ReadChar;
- end;
- until Quit;
- if InStringLength = 1 then begin
- SymLoc := InString[0];
- CurrSym := Char1;
- end else if Delim = '"' then
- CurrSym := Quote1
- else
- CurrSym := Apostrophe1;
- end;
- }
-
- Procedure WriteHex(num : integer);
-
- {
- This writes full 32 bit hexadecimal numbers.
- }
-
- var
- numary : array [1..8] of char;
- pos : integer;
- ch : Short;
- begin
- pos := 8;
- while (num <> 0) and (pos > 0) do begin
- ch := num and 15;
- if ch < 10 then
- numary[pos] := chr(ch + ord('0'))
- else
- numary[pos] := chr(ch + ord('A') - 10);
- pos := pos - 1;
- num := num shr 4;
- end;
- if pos = 8 then begin
- pos := 7;
- numary[8] := '0';
- end;
- write(OutFile, '$');
- for num := pos + 1 to 8 do
- write(OutFile, numary[num]);
- end;
-
- Procedure NextSymbol;
-
- {
- This is the workhorse lexical analysis routine. It sets
- currsym to the appropriate symbol number, sets symtext equal to
- whatever identifier is read, and symloc to the value of a literal
- integer.
- }
-
- begin
- Blanks;
- ErrorPtr := EQEnd;
- if EndOfFile then begin
- CurrentChar := Chr(0);
- CurrSym := EndText1; { I don't think this routine is ever hit }
- Return;
- end;
- if Alpha(CurrentChar) then
- readword
- else if isdigit(currentchar) then
- readnumber
- else begin
- case CurrentChar of
- '[' : begin
- CurrSym:= leftbrack1;
- ReadChar;
- end;
- ']' : begin
- CurrSym:= rightbrack1;
- ReadChar;
- end;
- '(' : begin
- CurrSym:= leftparent1;
- ReadChar;
- end;
- ')' : begin
- CurrSym:= rightparent1;
- ReadChar;
- end;
- '+' : begin
- CurrSym := plus1;
- ReadChar;
- end;
- '-' : begin
- CurrSym := minus1;
- ReadChar;
- end;
- '*' : begin
- CurrSym:= asterisk1;
- ReadChar;
- end;
- '/' : begin
- CurrSym := RealDiv1;
- ReadChar;
- end;
- '<' : begin
- ReadChar;
- if CurrentChar = '=' then begin
- CurrSym := notgreater1;
- ReadChar;
- end else if currentchar = '>' then begin
- CurrSym := notequal1;
- ReadChar;
- end else
- CurrSym:= less1;
- end;
- '=' : begin
- CurrSym:= equal1;
- ReadChar;
- end;
- '>' : begin
- ReadChar;
- if CurrentChar = '=' then begin
- CurrSym:= notless1;
- ReadChar;
- end else
- CurrSym:= greater1;
- end;
- ':' : begin
- ReadChar;
- if CurrentChar = '=' then begin
- CurrSym:= Becomes1;
- ReadChar;
- end else
- CurrSym:= colon1;
- end;
- ',' : begin
- CurrSym:= comma1;
- ReadChar;
- end;
- '.' : begin
- ReadChar;
- if CurrentChar = '.' then begin
- CurrSym:= DotDot1;
- ReadChar;
- end else
- CurrSym:= period1;
- end;
- ';' : begin
- CurrSym:= semicolon1;
- ReadChar;
- end;
- '\'': begin
- CurrSym:= apostrophe1;
- ReadChar;
- end;
- '"' : begin
- CurrSym:= quote1;
- ReadChar;
- end;
- '^' : begin
- CurrSym:= carat1;
- ReadChar;
- end;
- '@' : begin
- CurrSym := At1;
- ReadChar;
- end;
- '$' : ReadHex;
- '%' : ReadBinary;
- '\0' : CurrSym := EndText1;
- else begin
- Error("Unknown symbol.");
- ReadChar;
- end;
- end; { Case }
- end; { Else }
- end;
-